pp108 : Implementing Pagination

Implementing Pagination

This topic describes the implementation of pagination over Web services using the Process Platform cursor mechanism and the cordys.model plug-in available in the Process Platform HTML5 SDK.

You can implement the pagination over Web services using the Process Platform cursor mechanism and the cordys.model plug-in available in the Process Platform HTML5 SDK. Refer to Getting Started with the SDK for more information .

Pagination can be done in the mobile interfaces in one of the following ways:

  • Example 1: Pagination with buttons
  • Example 2: Pagination with endless scrolling list

Using an endless list is preferred to pagination buttons, as it is the most common approach in the mobile apps.

Example 1

This example is built on the Employees table from the Northwind Database . The app displays a set of three employees per page. The next and previous buttons are displayed, which invoke the model.getNextPage() and model.getPreviousPage() methods respectively. You can subscribe to the collection of the business objects using the model.read() API. You can invoke the methods model.hasNext() and model.hasPrevious() to disable or enable whenever the collection of business objects is modified.

Pagination with Buttons
<html>
    <head>
        <title>Employees</title>
        <meta content="width=device-width, initial-scale=1" name="viewport"/>
        <link href="/cordys/thirdparty/jquery/jquery.mobile.min.css" rel="stylesheet"/>
        <script src="/cordys/thirdparty/jquery/jquery.js" type="text/javascript"/>
        <script src="/cordys/thirdparty/jquery/jquery.mobile.min.js" type="text/javascript"/>
        <script src="/cordys/thirdparty/knockout/knockout.js" type="text/javascript"/>
        <script src="/cordys/html5/cordys.html5sdk.js" type="text/javascript"/>
        <script type="text/javascript"> $(function() { // Create a new model empModel = new $.cordys.model({ objectName: "Employees", // Name of the Business Object context : document.body, // Where the data is bound to read: { // Settings for the read method namespace: "http://schemas.cordys.com/NW", dataType: "json", method: "GetEmployeesObjects", // Parameters for the method parameters: { fromEmployeeID: "0", toEmployeeID: "99", cursor:{ '@numRows':4 } } } }); // Call the read method. This would fire the method with the namespace and parameters as specified in the read settings above. empModel.read(); // Subscribe to any change in the collection of Employees to enable/disable the next, previous buttons empModel.Employees.subscribe(function(){ // disable the previous button if there are no previous records in the cursor $("#btnPrevious").toggleClass("ui-disabled", ! empModel.hasPrevious()); // disable the next button if we are at the end of the cursor $("#btnNext").toggleClass("ui-disabled", ! empModel.hasNext()); }); }); // Called on clicking refresh button. Refreshes the page function refresh() { empModel.clear(); empModel.read(); } // Called on clicking the Next button. Gets the next set of records function getNext() { empModel.getNextPage(); } // Called on clicking the previous button. Gets the previous set of records function getPrevious() { empModel.getPreviousPage(); } </script>
    </head>
    <body>
        <div data-role="page" id="mainPage">
            <div data-role="header" data-theme="b">
                <a data-bind="click:refresh" data-icon="refresh">Refresh</a>
                <h1>Employees</h1>
                <div class="ui-btn-right" data-role="controlgroup" data-type="horizontal">
                    <a class="ui-disabled" data-bind="click:getPrevious"
                        data-icon="arrow-l" data-iconpos="notext"
                        data-role="button" id="btnPrevious">Previous</a>
                    <a class="ui-disabled" data-bind="click:getNext"
                        data-icon="arrow-r" data-iconpos="notext"
                        data-role="button" id="btnNext">Next</a>
                </div>
            </div>
            <div data-role="content" data-theme="b">
                <ul data-bind="foreach:Employees" data-inset="true"
                    data-role="listview" data-theme="c" id="employeeList">
                    <li>
                        <!-- ko if: typeof(Photo)!=="undefined" && Photo-->
                        <img class="ui-li-thumb ui-corner-tl" data-bind="attr: {src: 'data:image/bmp;base64,' + Photo.substring(104) }"/>
                        <!-- /ko -->
                        <!-- ko if: typeof(Photo)==="undefined" || (!Photo)-->
                        <img class="ui-li-thumb ui-corner-tl" src="/cordys/html5/demo/images/defaultphoto.jpg"/>
                        <!-- /ko -->
                        <h3 class="ui-li-heading">
                            <span data-bind="text:FirstName"/>
                            <span data-bind="text:LastName"/>
                        </h3>
                        <p class="ui-li-desc" data-bind="text:Address"/>
                        <p class="ui-li-desc">
                            <span data-bind="text:City"/>
                            <span data-bind="text:Country"/>
                        </p>
                    </li>
                </ul>
            </div>
        </div>
    </body>
</html>

Note:
Example 1 is similar to employeeslistwithnavigation.htm available in the demo folder in the Process Platform HTML5 SDK. For more information on the other demo pages in the Process Platform HTML5 SDK, r efer to Sample Pages .

Example 2

This is built on the Orders table from the Northwind Database. In an endless scrolling list, the next set of records is retrieved whenever the scroll appears below the rendered page and the result is appended to the existing list.

In this Web page, the next set of results are displayed by invoking model.getNextPage() on the scroll or touchmove event of the list content. You can subscribe to the collection of the business objects using model.read().

Pagination with Endless Scrolling List
<!DOCTYPE html>
<html>
    <head>
        <title>Orders</title>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <link rel="stylesheet" href="/cordys/thirdparty/jquery/cordys.min.css" type="text/css" />
        <link rel="stylesheet" href="/cordys/thirdparty/jquery/jquery.mobile.structure.min.css" type="text/css" />
        <script src="/cordys/thirdparty/jquery/jquery.js"></script>
        <script src="/cordys/thirdparty/jquery/jquery.mobile.min.js"></script>
        <script src="/cordys/thirdparty/jsrender/jsrender.js" type="text/javascript"></script>
        <script src="/cordys/html5/cordys.html5sdk.js" type="text/javascript"></script>
        <style type="text/css">
        </style>
    </head>
    <script id="ordersTemplate" type="text/x-jsrender">
        <li data-icon="false">
            <a href="#" data-transition="pop" class="ui-link-inherit">
            <div >
                <h3 class="ui-li-heading">Order {{:OrderID}}</h3>
                <p class="ui-li-desc">Customer :{{:CustomerID}}</p>
                <p class="ui-li-desc">Country :{{:ShipCountry}}</p>
            </div>
            </a>
        </li>
    </script>
    <script type="text/javascript">
        var orders = [],readNextOrders = false;
        var orderModel;
        $(function() {
        // Create a new model
        orderModel = new $.cordys.model({
            objectName: "Orders", // Name of the Business Object
            context : document.body, // Where the data is bound to
            read: {
                // Settings for the read method
                namespace: "http://schemas.cordys.com/NW",
                dataType: "json",
                method: "GetOrdersObjects",
                // Parameters for the method
                parameters: {
                    cursor:{
                        '@numRows':9
                    },
                    fromOrderID : "10248",
                    toOrderID : "10287"  
                }
            }
        });
         
        // Call the read method. Method is fired with namespace and parameters as specified above.
        orderModel.clear();
        orderModel.read().done(function(){
            readNextOrders = true;// only after read method getnextpage should fire 
            orders = orders.concat(orderModel.Orders);
            var html = $("#ordersTemplate").render(orders);
            $('#orderList')
            .html(html)
            .listview("refresh");
        });
     
    });
    //Specific to IE
    if (navigator.appName.indexOf("Microsoft Internet") != -1)
        $(window).scroll(function(){ fireScroll()});
    //getTouchEventName()
    $(document).on(getTouchEventName(),function(){ fireScroll()});
     
    function fireScroll() {
        var activePage = $.mobile.activePage ;
        if (activePage && activePage.attr("id") == "ordersPage") {
            // check whether scroll is near the bottom of the page
            if ($(window).scrollTop() + $(window).height() > (activePage.height() - 150)) {
                // readNextOrders is false initially to avoid the firing of getNextPage before read method
                if(readNextOrders && orderModel.hasNext()){
                    readNextOrders = false;
                    orderModel.getNextPage().done( function(){                      
                        orders = orders.concat(orderModel.Orders);
                        var html = $("#ordersTemplate").render(orders);
                        $('#orderList')
                        .html(html)
                        .listview("refresh");
                        readNextOrders = true;
                    }); 
                }
            }
        }
    }
     
    // This method returns 'touchmove' if device supports touch, else we will use 'scroll'
    function getTouchEventName(){
        try{
            document.createEvent("TouchEvent");
            return 'touchmove';
        }catch(e){
            return 'scroll';
        }
    }
    </script>
    <body>
        <div data-role="page" id="ordersPage">
            <div data-role="header" data-theme="b">
                <h1>Orders</h1>
            </div>
            <div data-role="content" data-theme="b">
                <ul id="orderList" data-role="listview" data-theme="c" data-inset="true">
                </ul>
            </div>
        </div>
    </body>
</html>  

Note:
The Example 2 is similar to orderslistwithswipe.htm available in the demo folder of the Process Platform HTML5 SDK. For more information on the other demo pages in the Process Platform HTML5 SDK, refer to Sample Pages .

Attachments: